<HTML><HEAD><TITLE>/home/steder/Projects/Tutorials/python/BobChat-v0.3/BobClient.py</TITLE></HEAD>
                  <BODY BGCOLOR=#FFFFFF>
                  <!--header-->
                  <!--script--><PRE><FONT COLOR=#1111CC>#!/usr/bin/env python</FONT>
<FONT COLOR=#1111CC># normalDate.py - version 1.3 - 2002/05/24</FONT>
<FONT COLOR=#1111CC># Author: Jeff Bauer, Rubicon Research - jbauer@rubic.com</FONT>
<FONT COLOR=#1111CC># License: Same as Python 2.1 or later</FONT>

<FONT COLOR=#3333CC><B>import</B></FONT> time
<FONT COLOR=#3333CC><B>from</B></FONT> types <FONT COLOR=#3333CC><B>import</B></FONT> IntType, ListType, StringType, TupleType

_bigBangScalar = -4345732  <FONT COLOR=#1111CC># based on (-9999, 1, 1) BC/BCE minimum</FONT>
_bigCrunchScalar = 2958463  <FONT COLOR=#1111CC># based on (9999,12,31) AD/CE maximum</FONT>
_daysInMonthNormal = [31,28,31,30,31,30,31,31,30,31,30,31]
_daysInMonthLeapYear = [31,29,31,30,31,30,31,31,30,31,30,31]
_dayOfWeekName = [<FONT COLOR=#115511>'Monday'</FONT>, <FONT COLOR=#115511>'Tuesday'</FONT>, <FONT COLOR=#115511>'Wednesday'</FONT>, <FONT COLOR=#115511>'Thursday'</FONT>,
                  <FONT COLOR=#115511>'Friday'</FONT>, <FONT COLOR=#115511>'Saturday'</FONT>, <FONT COLOR=#115511>'Sunday'</FONT>]
_monthName = [<FONT COLOR=#115511>'January'</FONT>, <FONT COLOR=#115511>'February'</FONT>, <FONT COLOR=#115511>'March'</FONT>, <FONT COLOR=#115511>'April'</FONT>, <FONT COLOR=#115511>'May'</FONT>, <FONT COLOR=#115511>'June'</FONT>,
              <FONT COLOR=#115511>'July'</FONT>,<FONT COLOR=#115511>'August'</FONT>,<FONT COLOR=#115511>'September'</FONT>,<FONT COLOR=#115511>'October'</FONT>,<FONT COLOR=#115511>'November'</FONT>,<FONT COLOR=#115511>'December'</FONT>]

<FONT COLOR=#3333CC><B>class</B></FONT><A NAME="NormalDateException"><FONT COLOR=#CC0000><B> NormalDateException</B></FONT></A>(Exception):
    <FONT COLOR=#115511>"""Exception class for NormalDate"""</FONT>
    <FONT COLOR=#3333CC><B>pass</B></FONT>

<FONT COLOR=#3333CC><B>class</B></FONT><A NAME="NormalDate"><FONT COLOR=#CC0000><B> NormalDate</B></FONT></A>:
    <FONT COLOR=#115511>"""
    NormalDate is a specialized class to handle dates without
    all the excess baggage (time zones, daylight savings, leap
    seconds, etc.) of other date structures.  The minimalist
    strategy greatly simplifies its implementation and use.

    Internally, NormalDate is stored as an integer with values
    in a discontinuous range of -99990101 to 99991231.  The
    integer value is used principally for storage and to simplify
    the user interface.  Internal calculations are performed by
    a scalar based on Jan 1, 1900.

    Valid NormalDate ranges include (-9999,1,1) B.C.E. through
    (9999,12,31) C.E./A.D.

    1.3 - Added weekOfYear() method submitted by Harri Pasanen.
    1.2 - Bugfix for Python2.2, which changed localtime's type
          to time.struct_time rather than a tuple.  Thanks to
          Paul Weimer for reporting this problem.  Added some,
          but not all, of Robin Becker's ideas he incorporated
          into ReportLab's version of normalDate.
    1.1 - Added exception in setNormalDate for bad integer;
          range() returns a list of normalDates rather than
          a list of integers.
    1.0 - No changes, except the version number.  After 3 years of use
            by various parties I think we can consider it stable.
    0.8 - added Prof. Stephen Walton's suggestion for a range method 
            - module author resisted the temptation to use lambda &lt;0.5 wink&gt;
    0.7 - added Dan Winkler's suggestions for __add__, __sub__ methods
    0.6 - modifications suggested by Kevin Digweed to fix:
            - dayOfWeek, dayOfWeekAbbrev, clone methods
            - permit NormalDate to be a better behaved superclass
    0.5 - minor tweaking
    0.4 - added methods __cmp__, __hash__
        - added Epoch variable, scoped to the module
        - added setDay, setMonth, setYear methods
    0.3 - minor touch-ups
    0.2 - fixed bug for certain B.C.E leap years
        - added Jim Fulton's suggestions for short alias class name =ND
          and __getstate__, __setstate__ methods

    Special thanks for ideas and suggestions:  
        Jim Fulton
        Kevin Digweed
        Paul Weimer
        Robin Becker
        Roedy Green
        Stephen Walton
    """</FONT>
    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__init__"><FONT COLOR=#CC0000><B> __init__</B></FONT></A>(self, normalDate=None):
        <FONT COLOR=#115511>"""
        Accept 1 of 4 values to initialize a NormalDate:
            1. None - creates a NormalDate for the current day
            2. integer in yyyymmdd format
            3. string in yyyymmdd format
            4. tuple in (yyyy, mm, dd) - localtime/gmtime can also be used
        """</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> normalDate <FONT COLOR=#3333CC><B>is</B></FONT> None:
            self.setNormalDate(time.localtime(time.time()))
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            self.setNormalDate(normalDate)

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="add"><FONT COLOR=#CC0000><B> add</B></FONT></A>(self, days):
        <FONT COLOR=#115511>"""add days to date; use negative integers to subtract"""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> <FONT COLOR=#3333CC><B>not</B></FONT> type(days) <FONT COLOR=#3333CC><B>is</B></FONT> IntType:
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException( \
                <FONT COLOR=#115511>'add method parameter must be integer type'</FONT>)
        self.normalize(self.scalar() + days)

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__add__"><FONT COLOR=#CC0000><B> __add__</B></FONT></A>(self, days):
        <FONT COLOR=#115511>"""add integer to normalDate and return a new, calculated value"""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> <FONT COLOR=#3333CC><B>not</B></FONT> type(days) <FONT COLOR=#3333CC><B>is</B></FONT> IntType:
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException( \
                <FONT COLOR=#115511>'__add__ parameter must be integer type'</FONT>)
        cloned = self.clone()
        cloned.add(days)
        <FONT COLOR=#3333CC><B>return</B></FONT> cloned

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="clone"><FONT COLOR=#CC0000><B> clone</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return a cloned instance of this normalDate"""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> self.__class__(self.normalDate)

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__cmp__"><FONT COLOR=#CC0000><B> __cmp__</B></FONT></A>(self, target):
        <FONT COLOR=#3333CC><B>if</B></FONT> target <FONT COLOR=#3333CC><B>is</B></FONT> None: 
            <FONT COLOR=#3333CC><B>return</B></FONT> 1
        <FONT COLOR=#3333CC><B>elif</B></FONT> <FONT COLOR=#3333CC><B>not</B></FONT> hasattr(target, <FONT COLOR=#115511>'normalDate'</FONT>):
            <FONT COLOR=#3333CC><B>return</B></FONT> 1
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            <FONT COLOR=#3333CC><B>return</B></FONT> cmp(self.normalDate, target.normalDate)

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="day"><FONT COLOR=#CC0000><B> day</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return the day as integer 1-31"""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> int(repr(self.normalDate)[-2:])

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="dayOfWeek"><FONT COLOR=#CC0000><B> dayOfWeek</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return integer representing day of week, Mon=0, Tue=1, etc."""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> apply(dayOfWeek, self.toTuple())

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="dayOfWeekAbbrev"><FONT COLOR=#CC0000><B> dayOfWeekAbbrev</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return day of week abbreviation for current date: Mon, Tue, etc."""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> _dayOfWeekName[self.dayOfWeek()][:3]

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="dayOfWeekName"><FONT COLOR=#CC0000><B> dayOfWeekName</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return day of week name for current date: Monday, Tuesday, etc."""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> _dayOfWeekName[self.dayOfWeek()]

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="dayOfYear"><FONT COLOR=#CC0000><B> dayOfYear</B></FONT></A>(self):
        <FONT COLOR=#115511>"""day of year"""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> self.isLeapYear():
            daysByMonth = _daysInMonthLeapYear
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            daysByMonth = _daysInMonthNormal
        priorMonthDays = 0
        <FONT COLOR=#3333CC><B>for</B></FONT> m <FONT COLOR=#3333CC><B>in</B></FONT> xrange(self.month() - 1):
            priorMonthDays = priorMonthDays + daysByMonth[m]
        <FONT COLOR=#3333CC><B>return</B></FONT> self.day() + priorMonthDays

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="daysBetweenDates"><FONT COLOR=#CC0000><B> daysBetweenDates</B></FONT></A>(self, normalDate):
        <FONT COLOR=#115511>"""
        return value may be negative, since calculation is 
        self.scalar() - arg
        """</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> type(normalDate) <FONT COLOR=#3333CC><B>is</B></FONT> _NormalDateType:
            <FONT COLOR=#3333CC><B>return</B></FONT> self.scalar() - normalDate.scalar()
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            <FONT COLOR=#3333CC><B>return</B></FONT> self.scalar() - NormalDate(normalDate).scalar()

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="daysInMonth"><FONT COLOR=#CC0000><B> daysInMonth</B></FONT></A>(self, month):
        <FONT COLOR=#115511>"""returns last day of the month as integer 28-31"""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> self.isLeapYear():
            <FONT COLOR=#3333CC><B>return</B></FONT> _daysInMonthLeapYear[month - 1]
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            <FONT COLOR=#3333CC><B>return</B></FONT> _daysInMonthNormal[month - 1]

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="equals"><FONT COLOR=#CC0000><B> equals</B></FONT></A>(self, target):
        <FONT COLOR=#3333CC><B>if</B></FONT> type(target) <FONT COLOR=#3333CC><B>is</B></FONT> _NormalDateType:
            <FONT COLOR=#3333CC><B>if</B></FONT> target <FONT COLOR=#3333CC><B>is</B></FONT> None:
                <FONT COLOR=#3333CC><B>return</B></FONT> self.normalDate <FONT COLOR=#3333CC><B>is</B></FONT> None
            <FONT COLOR=#3333CC><B>else</B></FONT>:
                <FONT COLOR=#3333CC><B>return</B></FONT> self.normalDate == target.normalDate
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="endOfMonth"><FONT COLOR=#CC0000><B> endOfMonth</B></FONT></A>(self):
        <FONT COLOR=#115511>"""returns (cloned) last day of month"""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> self.__class__(self.__repr__()[-8:-2] + \
                              str(self.lastDayOfMonth()))

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="firstDayOfMonth"><FONT COLOR=#CC0000><B> firstDayOfMonth</B></FONT></A>(self):
        <FONT COLOR=#115511>"""returns (cloned) first day of month"""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> self.__class__(self.__repr__()[-8:-2] + <FONT COLOR=#115511>"01"</FONT>)

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="formatUS"><FONT COLOR=#CC0000><B> formatUS</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return date as string in common US format: MM/DD/YY"""</FONT>
        d = self.__repr__()
        <FONT COLOR=#3333CC><B>return</B></FONT> <FONT COLOR=#115511>"%s/%s/%s"</FONT> % (d[-4:-2], d[-2:], d[-6:-4])

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="formatUSCentury"><FONT COLOR=#CC0000><B> formatUSCentury</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return date as string in 4-digit year US format: MM/DD/YYYY"""</FONT>
        d = self.__repr__()
        <FONT COLOR=#3333CC><B>return</B></FONT> <FONT COLOR=#115511>"%s/%s/%s"</FONT> % (d[-4:-2], d[-2:], d[-8:-4])

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__getstate__"><FONT COLOR=#CC0000><B> __getstate__</B></FONT></A>(self):
        <FONT COLOR=#115511>"""minimize persistent storage requirements"""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> self.normalDate

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__hash__"><FONT COLOR=#CC0000><B> __hash__</B></FONT></A>(self):
        <FONT COLOR=#3333CC><B>return</B></FONT> hash(self.normalDate)

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__int__"><FONT COLOR=#CC0000><B> __int__</B></FONT></A>(self):
        <FONT COLOR=#3333CC><B>return</B></FONT> self.normalDate

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="isLeapYear"><FONT COLOR=#CC0000><B> isLeapYear</B></FONT></A>(self):
        <FONT COLOR=#115511>"""
        determine if specified year is leap year, returning true (1) or 
        false (0)
        """</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> isLeapYear(self.year())

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="_isValidNormalDate"><FONT COLOR=#CC0000><B> _isValidNormalDate</B></FONT></A>(self, normalDate):
        <FONT COLOR=#115511>"""checks for date validity in [-]yyyymmdd format"""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> type(normalDate) <FONT COLOR=#3333CC><B>is</B></FONT> <FONT COLOR=#3333CC><B>not</B></FONT> IntType:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0
        <FONT COLOR=#3333CC><B>if</B></FONT> len(repr(normalDate)) &gt; 9:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0
        <FONT COLOR=#3333CC><B>if</B></FONT> normalDate &lt; 0:
            dateStr = <FONT COLOR=#115511>"%09d"</FONT> % normalDate
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            dateStr = <FONT COLOR=#115511>"%08d"</FONT> % normalDate
        <FONT COLOR=#3333CC><B>if</B></FONT> len(dateStr) &lt; 8:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0
        <FONT COLOR=#3333CC><B>elif</B></FONT> len(dateStr) == 9:
            <FONT COLOR=#3333CC><B>if</B></FONT> (dateStr[0] != <FONT COLOR=#115511>'-'</FONT> <FONT COLOR=#3333CC><B>and</B></FONT> dateStr[0] != <FONT COLOR=#115511>'+'</FONT>):
                <FONT COLOR=#3333CC><B>return</B></FONT> 0
        year = int(dateStr[:-4])
        <FONT COLOR=#3333CC><B>if</B></FONT> year &lt; -9999 <FONT COLOR=#3333CC><B>or</B></FONT> year &gt; 9999 <FONT COLOR=#3333CC><B>or</B></FONT> year == 0:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0    <FONT COLOR=#1111CC># note: zero (0) is not a valid year</FONT>
        month = int(dateStr[-4:-2])
        <FONT COLOR=#3333CC><B>if</B></FONT> month &lt; 1 <FONT COLOR=#3333CC><B>or</B></FONT> month &gt; 12:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0
        <FONT COLOR=#3333CC><B>if</B></FONT> isLeapYear(year):
            maxDay = _daysInMonthLeapYear[month - 1]
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            maxDay = _daysInMonthNormal[month - 1]
        day = int(dateStr[-2:])
        <FONT COLOR=#3333CC><B>if</B></FONT> day &lt; 1 <FONT COLOR=#3333CC><B>or</B></FONT> day &gt; maxDay:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0
        <FONT COLOR=#3333CC><B>if</B></FONT> year == 1582 <FONT COLOR=#3333CC><B>and</B></FONT> month == 10 <FONT COLOR=#3333CC><B>and</B></FONT> day &gt; 4 <FONT COLOR=#3333CC><B>and</B></FONT> day &lt; 15:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0  <FONT COLOR=#1111CC># special case of 10 days dropped: Oct 5-14, 1582</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> 1

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="lastDayOfMonth"><FONT COLOR=#CC0000><B> lastDayOfMonth</B></FONT></A>(self):
        <FONT COLOR=#115511>"""returns last day of the month as integer 28-31"""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> self.isLeapYear():
            <FONT COLOR=#3333CC><B>return</B></FONT> _daysInMonthLeapYear[self.month() - 1]
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            <FONT COLOR=#3333CC><B>return</B></FONT> _daysInMonthNormal[self.month() - 1]

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="localeFormat"><FONT COLOR=#CC0000><B> localeFormat</B></FONT></A>(self):
        <FONT COLOR=#115511>"""override this method to use your preferred locale format"""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> self.formatUS()

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="month"><FONT COLOR=#CC0000><B> month</B></FONT></A>(self):
        <FONT COLOR=#115511>"""returns month as integer 1-12"""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> int(repr(self.normalDate)[-4:-2])

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="monthAbbrev"><FONT COLOR=#CC0000><B> monthAbbrev</B></FONT></A>(self):
        <FONT COLOR=#115511>"""returns month as a 3-character abbreviation, i.e. Jan, Feb, etc."""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> _monthName[self.month() - 1][:3]

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="monthName"><FONT COLOR=#CC0000><B> monthName</B></FONT></A>(self):
        <FONT COLOR=#115511>"""returns month name, i.e. January, February, etc."""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> _monthName[self.month() - 1]

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="normalize"><FONT COLOR=#CC0000><B> normalize</B></FONT></A>(self, scalar):
        <FONT COLOR=#115511>"""convert scalar to normalDate"""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> scalar &lt; _bigBangScalar:
            msg = <FONT COLOR=#115511>"normalize(%d): scalar below minimum"</FONT> % \
                  _bigBangScalar
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(msg)
        <FONT COLOR=#3333CC><B>if</B></FONT> scalar &gt; _bigCrunchScalar:
            msg = <FONT COLOR=#115511>"normalize(%d): scalar exceeds maximum"</FONT> % \
                  _bigCrunchScalar
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(msg)
        <FONT COLOR=#3333CC><B>from</B></FONT> math <FONT COLOR=#3333CC><B>import</B></FONT> floor
        <FONT COLOR=#3333CC><B>if</B></FONT> scalar &gt;= -115860:
            year = 1600 + int(floor((scalar + 109573) / 365.2425))
        <FONT COLOR=#3333CC><B>elif</B></FONT> scalar &gt;= -693597:
            year = 4 + int(floor((scalar + 692502) / 365.2425))
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            year = -4 + int(floor((scalar + 695058) / 365.2425))
        days = scalar - firstDayOfYear(year) + 1
        <FONT COLOR=#3333CC><B>if</B></FONT> days &lt;= 0:
            year = year - 1
            days = scalar - firstDayOfYear(year) + 1
        daysInYear = 365
        <FONT COLOR=#3333CC><B>if</B></FONT> isLeapYear(year):
            daysInYear = daysInYear + 1
        <FONT COLOR=#3333CC><B>if</B></FONT> days &gt; daysInYear:
            year = year + 1
            days = scalar - firstDayOfYear(year) + 1
        <FONT COLOR=#1111CC># add 10 days if between Oct 15, 1582 and Dec 31, 1582</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> (scalar &gt;= -115860 <FONT COLOR=#3333CC><B>and</B></FONT> scalar &lt;= -115783):
            days = days + 10
        <FONT COLOR=#3333CC><B>if</B></FONT> isLeapYear(year):
            daysByMonth = _daysInMonthLeapYear
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            daysByMonth = _daysInMonthNormal
        dc = 0; month = 12
        <FONT COLOR=#3333CC><B>for</B></FONT> m <FONT COLOR=#3333CC><B>in</B></FONT> xrange(len(daysByMonth)):
            dc = dc + daysByMonth[m]
            <FONT COLOR=#3333CC><B>if</B></FONT> dc &gt;= days:
                month = m + 1
                <FONT COLOR=#3333CC><B>break</B></FONT>
        <FONT COLOR=#1111CC># add up the days in prior months</FONT>
        priorMonthDays = 0
        <FONT COLOR=#3333CC><B>for</B></FONT> m <FONT COLOR=#3333CC><B>in</B></FONT> xrange(month - 1):
            priorMonthDays = priorMonthDays + daysByMonth[m]
        day = days - priorMonthDays
        self.setNormalDate((year, month, day))

	<FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__radd__"><FONT COLOR=#CC0000><B> __radd__</B></FONT></A>(self,days):
		<FONT COLOR=#115511>"""for completeness"""</FONT>
		<FONT COLOR=#3333CC><B>return</B></FONT> self.__add__(days)

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="range"><FONT COLOR=#CC0000><B> range</B></FONT></A>(self, days):
        <FONT COLOR=#115511>"""Return a range of normalDates as a list.  Parameter
        may be an int or normalDate."""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> type(days) <FONT COLOR=#3333CC><B>is</B></FONT> <FONT COLOR=#3333CC><B>not</B></FONT> IntType:
            days = days - self  <FONT COLOR=#1111CC># if not int, assume arg is normalDate type</FONT>
        r = []
        <FONT COLOR=#3333CC><B>for</B></FONT> i <FONT COLOR=#3333CC><B>in</B></FONT> range(days):
            r.append(self + i)
        <FONT COLOR=#3333CC><B>return</B></FONT> r

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__repr__"><FONT COLOR=#CC0000><B> __repr__</B></FONT></A>(self):
        <FONT COLOR=#115511>"""print format: [-]yyyymmdd"""</FONT>
        <FONT COLOR=#1111CC># Note: When disassembling a NormalDate string, be sure to</FONT>
        <FONT COLOR=#1111CC># count from the right, i.e. epochMonth = int(`Epoch`[-4:-2]),</FONT>
        <FONT COLOR=#1111CC># or the slice won't work for dates B.C.</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> self.normalDate &lt; 0:
            <FONT COLOR=#3333CC><B>return</B></FONT> <FONT COLOR=#115511>"%09d"</FONT> % self.normalDate
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            <FONT COLOR=#3333CC><B>return</B></FONT> <FONT COLOR=#115511>"%08d"</FONT> % self.normalDate

	<FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__rsub__"><FONT COLOR=#CC0000><B> __rsub__</B></FONT></A>(self, v):
		<FONT COLOR=#3333CC><B>if</B></FONT> type(v) <FONT COLOR=#3333CC><B>is</B></FONT> IntType:
			<FONT COLOR=#3333CC><B>return</B></FONT> NormalDate(v) - self
		<FONT COLOR=#3333CC><B>else</B></FONT>:
			<FONT COLOR=#3333CC><B>return</B></FONT> v.scalar() - self.scalar()

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="scalar"><FONT COLOR=#CC0000><B> scalar</B></FONT></A>(self):
        <FONT COLOR=#115511>"""days since baseline date: Jan 1, 1900"""</FONT>
        (year, month, day) = self.toTuple()
        days = firstDayOfYear(year) + day - 1
        <FONT COLOR=#3333CC><B>if</B></FONT> self.isLeapYear():
            <FONT COLOR=#3333CC><B>for</B></FONT> m <FONT COLOR=#3333CC><B>in</B></FONT> xrange(month - 1):
                days = days + _daysInMonthLeapYear[m]
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            <FONT COLOR=#3333CC><B>for</B></FONT> m <FONT COLOR=#3333CC><B>in</B></FONT> xrange(month - 1):
                days = days + _daysInMonthNormal[m]
        <FONT COLOR=#3333CC><B>if</B></FONT> year == 1582:
            <FONT COLOR=#3333CC><B>if</B></FONT> month &gt; 10 <FONT COLOR=#3333CC><B>or</B></FONT> (month == 10 <FONT COLOR=#3333CC><B>and</B></FONT> day &gt; 4):
                days = days - 10
        <FONT COLOR=#3333CC><B>return</B></FONT> days

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="setDay"><FONT COLOR=#CC0000><B> setDay</B></FONT></A>(self, day):
        <FONT COLOR=#115511>"""set the day of the month"""</FONT>
        maxDay = self.lastDayOfMonth()
        <FONT COLOR=#3333CC><B>if</B></FONT> day &lt; 1 <FONT COLOR=#3333CC><B>or</B></FONT> day &gt; maxDay:
            msg = <FONT COLOR=#115511>"day is outside of range 1 to %d"</FONT> % maxDay
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(msg)
        (y, m, d) = self.toTuple()
        self.setNormalDate((y, m, day))

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="setMonth"><FONT COLOR=#CC0000><B> setMonth</B></FONT></A>(self, month):
        <FONT COLOR=#115511>"""set the month [1-12]"""</FONT>
        <FONT COLOR=#3333CC><B>if</B></FONT> month &lt; 1 <FONT COLOR=#3333CC><B>or</B></FONT> month &gt; 12:
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(<FONT COLOR=#115511>'month is outside range 1 to 12'</FONT>)
        (y, m, d) = self.toTuple()
        self.setNormalDate((y, month, d))

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="setNormalDate"><FONT COLOR=#CC0000><B> setNormalDate</B></FONT></A>(self, normalDate):
        <FONT COLOR=#115511>"""
        accepts date as scalar string/integer (yyyymmdd) or tuple 
        (year, month, day, ...)"""</FONT>
        _type = type(normalDate)
        <FONT COLOR=#3333CC><B>if</B></FONT> _type <FONT COLOR=#3333CC><B>is</B></FONT> IntType:
            self.normalDate = normalDate
        <FONT COLOR=#3333CC><B>elif</B></FONT> _type <FONT COLOR=#3333CC><B>is</B></FONT> StringType:
            <FONT COLOR=#3333CC><B>try</B></FONT>:
                self.normalDate = int(normalDate)
            <FONT COLOR=#3333CC><B>except</B></FONT> ValueError:
                <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(<FONT COLOR=#115511>"Bad integer: '%s'"</FONT> % normalDate)
        <FONT COLOR=#3333CC><B>elif</B></FONT> _type <FONT COLOR=#3333CC><B>in</B></FONT> (TupleType, ListType) <FONT COLOR=#3333CC><B>or</B></FONT> _type <FONT COLOR=#3333CC><B>is</B></FONT> _TimeType:
            self.normalDate = int(<FONT COLOR=#115511>"%04d%02d%02d"</FONT> % normalDate[:3])
        <FONT COLOR=#3333CC><B>elif</B></FONT> _type <FONT COLOR=#3333CC><B>is</B></FONT> _NormalDateType:
            self.normalDate = normalDate.normalDate
        <FONT COLOR=#3333CC><B>if</B></FONT> <FONT COLOR=#3333CC><B>not</B></FONT> self._isValidNormalDate(self.normalDate):
            msg = <FONT COLOR=#115511>"unable to setNormalDate(%s)"</FONT> % `normalDate`
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(msg)

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="setYear"><FONT COLOR=#CC0000><B> setYear</B></FONT></A>(self, year):
        <FONT COLOR=#3333CC><B>if</B></FONT> year == 0:
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(<FONT COLOR=#115511>'cannot set year to zero'</FONT>)
        <FONT COLOR=#3333CC><B>elif</B></FONT> year &lt; -9999:
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(<FONT COLOR=#115511>'year cannot be less than -9999'</FONT>)
        <FONT COLOR=#3333CC><B>elif</B></FONT> year &gt; 9999:
            <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(<FONT COLOR=#115511>'year cannot be greater than 9999'</FONT>)
        (y, m, d) = self.toTuple()
        self.setNormalDate((year, m, d))

    __setstate__ = setNormalDate

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="__sub__"><FONT COLOR=#CC0000><B> __sub__</B></FONT></A>(self, v):
        <FONT COLOR=#3333CC><B>if</B></FONT> type(v) <FONT COLOR=#3333CC><B>is</B></FONT> IntType:
            <FONT COLOR=#3333CC><B>return</B></FONT> self.__add__(-v)
        <FONT COLOR=#3333CC><B>return</B></FONT> self.scalar() - v.scalar()

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="toTuple"><FONT COLOR=#CC0000><B> toTuple</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return date as (year, month, day) tuple"""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> (self.year(), self.month(), self.day())

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="weekOfYear"><FONT COLOR=#CC0000><B> weekOfYear</B></FONT></A>(self):
        <FONT COLOR=#115511>"""returns the week of the year: 1-52"""</FONT>
        week = self.dayOfYear() / 7 + 1
        <FONT COLOR=#3333CC><B>if</B></FONT> week == 53:
            week = 1
        <FONT COLOR=#3333CC><B>return</B></FONT> week

    <FONT COLOR=#3333CC><B>def</B></FONT><A NAME="year"><FONT COLOR=#CC0000><B> year</B></FONT></A>(self):
        <FONT COLOR=#115511>"""return year in yyyy format, negative values indicate B.C."""</FONT>
        <FONT COLOR=#3333CC><B>return</B></FONT> int(repr(self.normalDate)[:-4])

<FONT COLOR=#1111CC>#################  Utility functions  #################</FONT>

<FONT COLOR=#3333CC><B>def</B></FONT><A NAME="bigBang"><FONT COLOR=#CC0000><B> bigBang</B></FONT></A>():
    <FONT COLOR=#115511>"""return lower boundary as a NormalDate"""</FONT>
    <FONT COLOR=#3333CC><B>return</B></FONT> NormalDate((-9999, 1, 1))

<FONT COLOR=#3333CC><B>def</B></FONT><A NAME="bigCrunch"><FONT COLOR=#CC0000><B> bigCrunch</B></FONT></A>():
    <FONT COLOR=#115511>"""return upper boundary as a NormalDate"""</FONT>
    <FONT COLOR=#3333CC><B>return</B></FONT> NormalDate((9999, 12, 31))

<FONT COLOR=#3333CC><B>def</B></FONT><A NAME="dayOfWeek"><FONT COLOR=#CC0000><B> dayOfWeek</B></FONT></A>(y, m, d):
    <FONT COLOR=#115511>"""return integer representing day of week, Mon=0, Tue=1, etc."""</FONT>
    <FONT COLOR=#3333CC><B>if</B></FONT> m == 1 <FONT COLOR=#3333CC><B>or</B></FONT> m == 2:
        m = m + 12
        y = y - 1
    <FONT COLOR=#3333CC><B>return</B></FONT> (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7

<FONT COLOR=#3333CC><B>def</B></FONT><A NAME="firstDayOfYear"><FONT COLOR=#CC0000><B> firstDayOfYear</B></FONT></A>(year):
    <FONT COLOR=#115511>"""number of days to the first of the year, relative to Jan 1, 1900"""</FONT>
    <FONT COLOR=#3333CC><B>if</B></FONT> type(year) <FONT COLOR=#3333CC><B>is</B></FONT> <FONT COLOR=#3333CC><B>not</B></FONT> IntType:
        msg = <FONT COLOR=#115511>"firstDayOfYear() expected integer, got %s"</FONT> % type(year)
        <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(msg)
    <FONT COLOR=#3333CC><B>if</B></FONT> year == 0:
        <FONT COLOR=#3333CC><B>raise</B></FONT> NormalDateException(<FONT COLOR=#115511>'first day of year cannot be zero (0)'</FONT>)
    <FONT COLOR=#3333CC><B>elif</B></FONT> year &lt; 0:  <FONT COLOR=#1111CC># BCE calculation</FONT>
        firstDay = (year * 365) + int((year - 1) / 4) - 693596
    <FONT COLOR=#3333CC><B>else</B></FONT>:           <FONT COLOR=#1111CC># CE calculation</FONT>
        leapAdjust = int((year + 3) / 4)
        <FONT COLOR=#3333CC><B>if</B></FONT> year &gt; 1600:
            leapAdjust = leapAdjust - int((year + 99 - 1600) / 100) + \
                         int((year + 399 - 1600) / 400)
        firstDay = year * 365 + leapAdjust - 693963
        <FONT COLOR=#3333CC><B>if</B></FONT> year &gt; 1582:
            firstDay = firstDay - 10
    <FONT COLOR=#3333CC><B>return</B></FONT> firstDay

<FONT COLOR=#3333CC><B>def</B></FONT><A NAME="isLeapYear"><FONT COLOR=#CC0000><B> isLeapYear</B></FONT></A>(year):
    <FONT COLOR=#115511>"""determine if specified year is leap year, returns Python boolean"""</FONT>
    <FONT COLOR=#3333CC><B>if</B></FONT> year &lt; 1600:
        <FONT COLOR=#3333CC><B>if</B></FONT> year % 4:
            <FONT COLOR=#3333CC><B>return</B></FONT> 0
        <FONT COLOR=#3333CC><B>else</B></FONT>:
            <FONT COLOR=#3333CC><B>return</B></FONT> 1
    <FONT COLOR=#3333CC><B>elif</B></FONT> year % 4 != 0:
        <FONT COLOR=#3333CC><B>return</B></FONT> 0
    <FONT COLOR=#3333CC><B>elif</B></FONT> year % 100 != 0:
        <FONT COLOR=#3333CC><B>return</B></FONT> 1
    <FONT COLOR=#3333CC><B>elif</B></FONT> year % 400 != 0:
        <FONT COLOR=#3333CC><B>return</B></FONT> 0
    <FONT COLOR=#3333CC><B>else</B></FONT>:
        <FONT COLOR=#3333CC><B>return</B></FONT> 1

ND=NormalDate
Epoch=bigBang()
_NormalDateType = type(Epoch)
_TimeType = type(time.localtime(time.time()))

<FONT COLOR=#3333CC><B>if</B></FONT> __name__ == <FONT COLOR=#115511>'__main__'</FONT>:
    today = ND()
    <FONT COLOR=#3333CC><B>print</B></FONT> <FONT COLOR=#115511>"NormalDate test:"</FONT>
    <FONT COLOR=#3333CC><B>print</B></FONT> <FONT COLOR=#115511>"  Today (%s) is: %s %s"</FONT> % \
          (today, today.dayOfWeekAbbrev(), today.localeFormat())
    yesterday = today - 1
    <FONT COLOR=#3333CC><B>print</B></FONT> <FONT COLOR=#115511>"  Yesterday was: %s %s"</FONT> % \
          (yesterday.dayOfWeekAbbrev(), yesterday.localeFormat())
    tomorrow = today + 1
    <FONT COLOR=#3333CC><B>print</B></FONT> <FONT COLOR=#115511>"  Tomorrow will be: %s %s"</FONT> % \
          (tomorrow.dayOfWeekAbbrev(), tomorrow.localeFormat())
    <FONT COLOR=#3333CC><B>print</B></FONT> <FONT COLOR=#115511>"  Days between tomorrow and yesterday: %d"</FONT> % \
          (tomorrow - yesterday)
</PRE>
                  <!--footer-->
                  </BODY>
